package top.aicey.ai.sparring.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import top.aicey.ai.sparring.common.constants.AIConstants;
import top.aicey.ai.sparring.common.constants.EntityConstants;
import top.aicey.ai.sparring.common.holder.SparringContext;
import top.aicey.ai.sparring.dto.enums.EvaluationStatusEnum;
import top.aicey.ai.sparring.dto.llm.EvaluateScoreInfo;
import top.aicey.ai.sparring.dto.res.EvaluationUserSceneHistoryResponse;
import top.aicey.ai.sparring.entity.Scene;
import top.aicey.ai.sparring.entity.SceneInstanceEvaluation;
import top.aicey.ai.sparring.mapper.SceneInstanceEvaluationMapper;
import top.aicey.ai.sparring.service.ISceneInstanceEvaluationService;

/**
 * <p>
 * 用户评价内容 服务实现类
 * </p>
 *
 * @author 白杨
 * @since 2025-01-14
 */
@Service
public class SceneInstanceEvaluationServiceImpl extends
    ServiceImpl<SceneInstanceEvaluationMapper, SceneInstanceEvaluation> implements ISceneInstanceEvaluationService {

    @Override
    public SceneInstanceEvaluation getByInstanceId(String instanceId) {
        return this.getOne(Wrappers.query(SceneInstanceEvaluation.class)
            .eq(EntityConstants.INSTANCE_ID, instanceId));
    }

    @Override
    public boolean initBySparringContext(SparringContext context) {
        if (this.exists(Wrappers.query(SceneInstanceEvaluation.class)
            .eq(EntityConstants.MODULE_ID,context.getModuleId()).eq(EntityConstants.INSTANCE_ID,context.getInstanceId()))){
            return false;
        }

        SceneInstanceEvaluation evaluation = new SceneInstanceEvaluation();
        evaluation.setSceneId(context.getSceneId());
        evaluation.setModuleId(context.getModuleId());
        evaluation.setInstanceId(context.getInstanceId());
        evaluation.setStatus(EvaluationStatusEnum.PROGRESS.getValue());
        evaluation.setCreatedBy(context.getUserId());
        evaluation.setUpdatedBy(context.getUserId());
        evaluation.setCreatedAt(LocalDateTime.now());
        evaluation.setUpdatedAt(LocalDateTime.now());
        return this.save(evaluation);
    }

    @Override
    public void updateEvaluateScoreInfoToComplete(String instanceId, EvaluateScoreInfo evaluateScoreInfo) {
        SceneInstanceEvaluation evaluation = this.getByInstanceId(instanceId);
        evaluation = this.buildEvaluateScoreInfoToEvaluation(evaluation, evaluateScoreInfo);
        this.updateById(evaluation);
    }

    @Override
    public PageInfo<SceneInstanceEvaluation> pageByParams(Integer pageNumber, Integer pageSize, String moduleId,
        Long sceneId, Long userId) {
        Page<SceneInstanceEvaluation> page = PageHelper.startPage(pageNumber, pageSize);
        QueryWrapper<SceneInstanceEvaluation> queryWrapper = Wrappers.query(SceneInstanceEvaluation.class)
            .eq(EntityConstants.SCENE_ID, sceneId).eq(EntityConstants.MODULE_ID, moduleId);

        if (!Objects.isNull(userId)){
            queryWrapper.eq(EntityConstants.CREATED_BY,userId);
        }

        this.list(queryWrapper);
        return page.toPageInfo();
    }

    @Override
    public void updateEvaluateScoreInfoToFail(String instanceId, Scene scene) {
        SceneInstanceEvaluation evaluation = this.getByInstanceId(instanceId);
        evaluation = this.buildFailToEvaluation(evaluation,scene);
        this.updateById(evaluation);
    }

    @Override
    public boolean completeByInstanceId(String moduleId, String instanceId) {
        return this.exists(Wrappers.query(SceneInstanceEvaluation.class)
            .eq(EntityConstants.MODULE_ID,moduleId)
            .eq(EntityConstants.INSTANCE_ID,instanceId)
            .eq(EntityConstants.STATUS,EvaluationStatusEnum.COMPLETE.getValue())
        );
    }

    @Override
    public List<EvaluationUserSceneHistoryResponse> sceneHistory(Long sceneId, String userId, Integer limit) {
        List<SceneInstanceEvaluation> list = this.list(Wrappers.query(SceneInstanceEvaluation.class)
            .eq(EntityConstants.STATUS, EvaluationStatusEnum.COMPLETE.getValue())
            .eq(EntityConstants.SCENE_ID, sceneId)
            .eq(EntityConstants.CREATED_BY, userId)
            .orderByDesc(EntityConstants.UPDATED_AT).last(" limit " + limit));

        List<EvaluationUserSceneHistoryResponse> responses = Lists.newArrayList();

        for (SceneInstanceEvaluation evaluation : list) {
            EvaluationUserSceneHistoryResponse response = new EvaluationUserSceneHistoryResponse();
            response.setInstanceId(evaluation.getInstanceId());
            response.setTime(evaluation.getCreatedAt());
            response.setScore(evaluation.getScore());
            responses.add(response);
        }
        return responses;
    }


    private SceneInstanceEvaluation buildEvaluateScoreInfoToEvaluation(SceneInstanceEvaluation evaluation, EvaluateScoreInfo evaluateScoreInfo){
        double asDouble = evaluateScoreInfo.getDimensionScore().values().stream().mapToInt(Integer::intValue).average().getAsDouble();
        evaluation.setContent(JSON.toJSONString(evaluateScoreInfo));
        evaluation.setScore(new BigDecimal(asDouble).intValue());
        evaluation.setStatus(EvaluationStatusEnum.COMPLETE.getValue());
        evaluation.setUpdatedAt(LocalDateTime.now());
        return evaluation;
    }


    private SceneInstanceEvaluation buildFailToEvaluation(SceneInstanceEvaluation evaluation, Scene scene) {
        EvaluateScoreInfo evaluateScoreInfo = new EvaluateScoreInfo();
        evaluateScoreInfo.setComment(AIConstants.FAIL_COMMENT);

        String dimensions = scene.getDimensions();
        List<String> dimensionList = Splitter.on(AIConstants.DIMENSIONS_SPLIT).trimResults().splitToList(dimensions);

        Map<String,Integer> dimensionMap = Maps.newHashMap();

        for (String dimension : dimensionList) {
            dimensionMap.put(dimension,AIConstants.DIMENSION_DEFAULT_SCORE);
        }
        evaluateScoreInfo.setDimensionScore(dimensionMap);
        evaluation.setContent(JSON.toJSONString(evaluateScoreInfo));
        evaluation.setStatus(EvaluationStatusEnum.COMPLETE.getValue());
        evaluation.setScore(AIConstants.DIMENSION_DEFAULT_SCORE);
        evaluation.setUpdatedAt(LocalDateTime.now());
        return evaluation;
    }
}
